package com.zhenyi.youqu.api;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.joda.time.DateTime;
import org.joda.time.Duration;

import com.cjw.model.DBMap;
import com.jfinal.aop.Before;
import com.jfinal.aop.Clear;
import com.jfinal.core.Controller;
import com.jfinal.kit.HashKit;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.JsonKit;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.weixin.sdk.api.PaymentApi;
import com.jfinal.weixin.sdk.api.PaymentApi.TradeType;
import com.jfinal.weixin.sdk.kit.IpKit;
import com.jfinal.weixin.sdk.kit.PaymentKit;
import com.jfinal.weixin.sdk.utils.HttpUtils;
import com.utils.interceptor.TestInterceptor;
import com.wxpay.utils.MD5Util;
import com.youqu.common.model.YqApp;
import com.youqu.common.model.YqOrder;
import com.youqu.common.model.YqOrderInfo;
import com.youqu.common.model.YqProduct;
import com.youqu.common.model.YqSaleRecord;
import com.youqu.common.model.YqShop;
import com.youqu.common.model.YqShopUser;
import com.youqu.common.model.YqUser;
import com.zhenyi.core.interceptor.ExceptionInterceptor;
import com.zhenyi.core.interceptor.SignInterceptor;
import com.zhenyi.core.wechatPay.PayUtils;
import com.zhenyi.youqu.core.YQController;
import com.zhenyi.youqu.core.ZHSMSUtils;
import com.zhenyi.youqu.interceptor.YQSignInterceptor;
import com.zhenyi.youqu.task.GroupTask;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.URLUtil;

public class ApiController extends YQController {

	// protected final String APP_ID = PropKit.get("YQ_APP_ID", "");
	// protected final String APP_SECRET = PropKit.get("YQ_APP_SECRET", "");
	// protected final String PARTNER = PropKit.get("YQ_PARTNER", "");
	// protected final String NOTIFY_URL = PropKit.get("YQ_NOTIFY_URL", "");
	// protected final String PARTNER_KEY = PropKit.get("YQ_PARTNER_KEY", "");
	// protected final String REFUND_NOTIFY_URL =
	// PropKit.get("YQ_REFUND_NOTIFY_URL", "");
	// protected final String SSL_PATH = PathUtils.getFile("cert", APP_ID,
	// "apiclient_cert.p12");
	// protected final PayUtils payUtils = new PayUtils(APP_ID, PARTNER,
	// PARTNER_KEY, SSL_PATH);

	public void testali() {
		YqApp app = getApp();
		YqOrder order = new YqOrder(app);
		order.setOutTradeNo(YqOrder.genTradeNo());
		order.setBody("商品");
		order.setDetail("详情");
		order.setProductId("productId");
		order.save();
		order.pushAliOrder();
		renderSuccess(order);
	}

	@Clear
	public void qrcode() {
		String text = getPara("text");
		if (StrKit.isBlank(text)) {
			renderError(404);
			return;
		}
		redirect("/api/qrcode?size=200&lt=1&text=" + text);
		// http://release.zhen-yee.com/yq/api?text=4L0B1Mwb
	}

	/**
	 * 二维码图片支付
	 */
	private final int MODE_QRCODE = 1;
	/**
	 * 刷卡支付
	 */
	private final int MODE_MICROPAY = 2;

	@Override
	public void index() {
		renderSuccess();
	}

	@Clear
	public void timestamp() {
		Long time = System.currentTimeMillis() / 1000;
		String now = DateUtil.now();
		Ret ret = Ret.by("timestamp", time).set("now", now);
		renderSuccess(ret);
	}

	/**
	 * 票券核销
	 */
	@Before({ ExceptionInterceptor.class, YQSignInterceptor.class })
	public void use() {
		String code = getPara("code");
		Long suid = getParaToLong("suid");
		if (suid == null) {
			renderFailure();
			return;
		}
		YqShopUser shopUser = YqShopUser.dao.findById(suid);
		if (shopUser == null) {
			renderFailure(401, "无效账户，请重新登录");
			return;
		}
		Long shopId = shopUser.getShopId();
		if (shopId == null) {
			renderFailure(500, "账户未设置所属商户");
			return;
		}
		long[] decodes = HASHID.decode(code);
		if (decodes.length == 0) {
			renderFailure(500, "无效二维码");
			return;
		}
		Long orderId = decodes[0];
		YqOrderInfo orderInfo = YqOrderInfo.dao.findById(orderId);
		if (orderInfo == null) {
			renderFailure(404, "订单不存在");
			return;
		}
		YqProduct product = YqProduct.dao.findById(orderInfo.getProductId());
		if (product == null) {
			renderFailure(404, "商品不存在");
			return;
		}
		if (!product.getShopId().equals(shopId)) {
			renderFailure(500, "该二维码不属于当前账户的商户");
			return;
		}
		// if (orderInfo.getIsUsed().equals(1)) {
		// renderFailure(500, "该二维码已核销");
		// return;
		// }
		// if (orderInfo.getIsMutiUse().equals(1)) {
		// if (orderInfo.getUseCount() >= orderInfo.getUseLimit()) {
		// if (!orderInfo.getIsUsed().equals(1)) {
		// orderInfo.setIsUsed(1);
		// orderInfo.update();
		// }
		// renderFailure(500, "使用次数已用尽");
		// return;
		// }
		// orderInfo.setUseCount(orderInfo.getUseCount() + 1);
		// if (orderInfo.getUseCount() >= orderInfo.getUseLimit()) {
		// orderInfo.setIsUsed(1);
		// }
		// orderInfo.update();
		// } else {
		// orderInfo.setIsUsed(1);
		// orderInfo.update();
		// }
		if (orderInfo.getCardType().equals(0)) {
			renderFailure("此二维码非卡券，不可核销");
			return;
		}

		DBMap map = new DBMap();
		map.put("cardType", orderInfo.getCardType());

		if (orderInfo.getCardType().equals(1)) { // 次卡
			if (orderInfo.getUseCount() >= orderInfo.getUseLimit()) {
				if (!orderInfo.getIsUsed().equals(1)) {
					orderInfo.setIsUsed(1);
					orderInfo.update();
				}
				renderFailure(500, "使用次数已用尽");
				return;
			}
			orderInfo.setUseCount(orderInfo.getUseCount() + 1);
			// if (orderInfo.getUseCount() >= orderInfo.getUseLimit()) {
			// orderInfo.setIsUsed(1);
			// }
			orderInfo.update();
			map.put("useLimit", orderInfo.getUseLimit());
			map.put("useCount", orderInfo.getUseCount());
		} else if (orderInfo.getCardType().equals(2)) { // 日卡
			YqOrder order = YqOrder.dao.findById(orderId);
			DateTime startDate = new DateTime(order.getAddTime());
			DateTime endDate = startDate.plusDays(orderInfo.getCardAvailableDay());
			endDate = endDate.secondOfDay().withMaximumValue();
			if (endDate.isBeforeNow()) {
				renderFailure(500, "该卡券已过期");
				return;
			}
			orderInfo.setUseCount(orderInfo.getUseCount() + 1);
			orderInfo.update();
			map.put("daysLeft", new Duration(DateTime.now(), endDate).getStandardDays());
			map.put("useCount", orderInfo.getUseCount());
		} else if (orderInfo.getCardType().equals(3)) { // 过期卡
			DateTime endDate = new DateTime(orderInfo.getCardExpire());
			if (endDate.isBeforeNow()) {
				renderFailure(500, "该卡券已过期");
				return;
			}
			orderInfo.setUseCount(orderInfo.getUseCount() + 1);
			orderInfo.update();
			map.put("expireDay", new DateTime(orderInfo.getCardExpire()).toString("yyyy-MM-dd"));
			map.put("useCount", orderInfo.getUseCount());
		} else {
			renderFailure("不可核销");
			return;
		}

		// 新增核销记录
		YqSaleRecord record = new YqSaleRecord();
		record.setOrderId(orderInfo.getOrderId());
		record.setUserId(orderInfo.getUserId());
		YqUser user = YqUser.dao.findById(orderInfo.getUserId());
		if (user != null) {
			record.setUserName(user.getNickName());
		}
		record.setProductId(product.getId());
		record.setProductName(product.getTitle());
		record.setShopId(shopUser.getShopId());
		YqShop shop = YqShop.dao.findById(shopUser.getShopId());
		if (shop != null) {
			record.setShopName(shop.getName());
		}
		record.setShopUserId(shopUser.getId());
		record.setShopUserName(shopUser.getName());
		record.setType(1); // 核销
		record.save();

		renderSuccess(map);
	}

	public void payment() {
		String data = getPara("data", "");
		data = "```\"\"''";
		DBMap map = new DBMap();
		map.put("data", data);
		String json = JsonKit.toJson(map);
		String code = URLUtil.encode(json);
		renderSuccess(code);
	}

	/**
	 * 更新团购信息
	 * 
	 * @Time 2019年1月12日 下午2:03:45
	 */
	@Before(TestInterceptor.class)
	public void updateGroups() {
		GroupTask groupTask = new GroupTask();
		new Thread(groupTask).start();
		renderSuccess();
	}

	@Before(TestInterceptor.class)
	public void close() {
		// Long orderId = getParaToLong("orderId");
		String code = getPara("code");
		Long orderId;
		try {
			orderId = YqOrder.LONG_HASHID.decode(code)[0];

			YqOrder order = YqOrder.dao.findById(orderId);
			if (order == null) {
				renderFailure(404, "order not found");
				return;
			}
			String out_trade_no = order.getOutTradeNo();
			YqApp app = order.getApp();
			String appId = app.getWechatMiniAppId();
			String partner = app.getWechatPartner();
			String partnetKey = app.getWechatPartnerKey();
			Map<String, String> result = PaymentApi.closeOrder(appId, partner, partnetKey, out_trade_no);
			order.updateOrderStatus();
			renderSuccess(result);

		} catch (Exception e) {
			e.printStackTrace();
			renderFailure();
		}
	}

	@Before(TestInterceptor.class)
	public void query() {
		// Long orderId = getParaToLong("orderId");
		String code = getPara("code");
		Long orderId;
		try {
			orderId = YqOrder.LONG_HASHID.decode(code)[0];

			YqOrder order = YqOrder.dao.findById(orderId);
			if (order == null) {
				renderFailure(404, "order not found");
				return;
			}
			Map<String, String> query = order.updateOrderStatus();
			renderSuccess(query);

		} catch (Exception e) {
			e.printStackTrace();
			renderFailure();
		}
	}

	/**
	 * 签名校验接口
	 */
	@Clear
	public void signTool() {
		// String sign = SignInterceptor.genSign(this);
		// renderSuccess(sign);
		Controller controller = this;
		Map<String, String> params = new HashMap<String, String>();
		ArrayList<String> aList = Collections.list(controller.getParaNames());
		for (String string : aList) {
			params.put(string, controller.getPara(string));
		}
		TreeMap<String, String> sortedParams = new TreeMap<String, String>(params);
		// 遍历排序后的字典，将所有参数按"key=value"格式拼接在一起
		StringBuilder sb = new StringBuilder();
		for (Entry<String, String> param : sortedParams.entrySet()) {
			String value = param.getValue();
			if (StrKit.isBlank(value)) {
				continue;
			}
			String key = param.getKey();
			if ("sign".equals(key)) {
				continue;
			}
			if ("token".equals(key)) {
				// 不校验token
				continue;
			}
			if ("str".equals(key)) {
				// str 是附加参数 用来debug
				continue;
			}
			// if ("version".equals(key)) {
			// // 不校验版本信息
			// continue;
			// }
			sb.append(key).append("=");
			sb.append(value);
			sb.append("&");
		}
		String string = sb.toString();
		String genSign = MD5Util.MD5Encode(string, "utf-8");

		String sign = getPara("sign");
		boolean isValidated = genSign.equals(sign);
		DBMap map = new DBMap();
		map.put("signStr", string);
		map.put("sign", genSign);
		map.put("isValidated", isValidated);
		renderSuccess(map);
	}

	@Before(TestInterceptor.class)
	public void refund() {
		Long orderId = getParaToLong("orderId");
		if (orderId == null) {
			renderError(404);
			return;
		}
		YqOrder order = YqOrder.dao.findById(orderId);
		if (order == null) {
			renderFailure("no order");
			return;
		}
		String fee = getPara("fee");
		String refundFee = StrKit.isBlank(fee) ? order.getPaid() + "" : fee;
		// String out_trade_no = order.getOutTradeNo();
		// Map<String, String> query = PaymentApi.queryByOutTradeNo(APP_ID,
		// PARTNER, PARTNER_KEY, out_trade_no);
		// if (PropKit.getBoolean("devMode", false)) {
		// System.out.println(JsonKit.toJson(query));
		// }
		// String trade_state = query.get("trade_state");
		// if (!("REFUND".equals(trade_state) || "SUCCESS".equals(trade_state)))
		// {
		// LogKit.info("订单支付状态非SUCCESS");
		// renderFailure("订单支付状态非SUCCESS");
		// return;
		// }
		// String refundNo = out_trade_no + "-refund-" +
		// RandomUtil.randomString(3);
		// String total_fee = order.getTotalFee();
		// Map<?, ?> refund = payUtils.refundOrderNo(out_trade_no, total_fee,
		// refundFee, refundNo, REFUND_NOTIFY_URL);
		// boolean flag = PayUtils.isXMLSuccess(refund);
		// renderSuccess(refund);

		renderSuccess(order.refund(refundFee));
	}

	// @Before(TestInterceptor.class)
	// public void refund2() {
	// String no = getPara("no");
	// String fee = getPara("fee");
	// String refundNo = no + "-refund-" + RandomUtil.randomString(3);
	// System.out.println("refundNo " + refundNo);
	// Map<?, ?> refund = payUtils.refundOrderNo(no, fee, fee, refundNo,
	// REFUND_NOTIFY_URL);
	// renderSuccess(refund);
	// }

	public void recv() {
		String json = HttpKit.readData(getRequest());
		System.out.println(json);
		renderText(json);
	}

	public void reverse() {
		String code = getPara("code");
		Long orderId;
		try {
			orderId = YqOrder.LONG_HASHID.decode(code)[0];

			YqOrder order = YqOrder.dao.findById(orderId);
			if (order == null) {
				renderFailure(404, "order not found");
				return;
			}
			PayUtils payUtils = order.getPayUtils();
			Map<String, String> query = payUtils.reverse(order.getOutTradeNo());
			renderSuccess(query);

		} catch (Exception e) {
			e.printStackTrace();
			renderFailure();
		}
	}

	@Before(YQSignInterceptor.class)
	public void pay() {
		String ip = IpKit.getRealIpV2(getRequest());
		String key = "YQ_PAY_IP_" + ip;
		if (cache.get(key) != null) {
			renderFailure("too many connections");
			return;
		}
		cache.setex(key, 1, ip);
		String total = getPara("total");
		try {
			int price = Integer.parseInt(total);
			if (price <= 0) {
				renderFailure("total错误");
				return;
			}
		} catch (Exception e) {
			renderFailure("total错误");
			return;
		}
		String body = getPara("body", "商品");
		if (StrKit.notBlank(body)) {
			if (body.length() >= 200) {
				renderFailure("body长度错误");
				return;
			}
		}
		String detail = getPara("detail", "");
		if (StrKit.notBlank(detail)) {
			if (detail.length() >= 200) {
				renderFailure("detail长度错误");
				return;
			}
		}
		String goodsTag = getPara("goodsTag", "");
		if (StrKit.notBlank(goodsTag)) {
			if (goodsTag.length() >= 200) {
				renderFailure("goodsTag长度错误");
				return;
			}
		}
		String productId = getPara("productId", "商品标识");
		if (StrKit.notBlank(productId)) {
			if (productId.length() >= 200) {
				renderFailure("productId长度错误");
				return;
			}
		}
		String attach = getPara("attach", "");
		String notifyUrl = getPara("notifyUrl", "");
		String mark = getPara("mark", "");
		String data = getPara("data", "");

		// 单品优惠用到
		// https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_101&index=1
		// String version = getPara("version", "");

		if (StrKit.notBlank(data)) {
			if (data.length() >= 200) {
				renderFailure("data长度错误");
				return;
			}
		}
		String totalFee = total;
		// String shop = getPara("shop", "");
		// if (StrKit.isBlank(shop)) {
		// renderFailure("商户错误");
		// return;
		// }
		Long shopId = 2L;
		// try {
		// shopId = HASHID.decode(shop)[0];
		// } catch (Exception e) {
		// renderFailure("商户错误");
		// return;
		// }

		YqShop shop = YqShop.dao.findById(shopId);
		YqApp app = shop.getApp();
		/**
		 * 支付模式,默认二维码支付
		 */
		int mode = getParaToInt("mode", MODE_QRCODE);

		YqOrder order = new YqOrder(app);
		order.setIp(ip);
		order.setType(YqOrder.TYPE_THIRD);
		order.setNotifyUrl(notifyUrl);
		order.setTotalFee(totalFee);
		order.setMark(mark);
		order.setAttach(attach);
		// order.setMchId(PARTNER);
		// order.setAppId(APP_ID);
		order.setProductId(productId);
		order.setBody(body);
		order.setDetail(detail);
		order.setGoodsTag(goodsTag);
		order.setData(data);
		order.setShopId(shopId);
		order.save();
		String outTradeNo = YqOrder.genTradeNo() + YqOrder.MIN_HASHID.encode(order.getId());
		order.setOutTradeNo(outTradeNo);
		order.update();

		if (mode == MODE_MICROPAY) {
			/**
			 * 刷卡支付
			 */
			String authCode = getPara("authCode");
			if (StrKit.isBlank(authCode)) {
				renderFailure("authCode empty");
				return;
			}
			renderFailure("未支持");
			boolean flag = genMircoPay(outTradeNo, body, totalFee, detail, goodsTag, attach, authCode,
					app.getWechatMiniAppId(), app.getWechatPartner(), app.getWechatPartnerKey());
			if (!flag) {
				renderFailure("mirco pay fail");
				return;
			}
			DBMap responseMap = new DBMap();
			responseMap.put("outTradeNo", outTradeNo);
			renderSuccess(responseMap);
			return;
		}

		String tradeType = TradeType.NATIVE.name();
		Map<String, String> result = genPay(outTradeNo, body, totalFee, detail, goodsTag, productId, attach, tradeType,
				order.getAppId(), order.getMchId(), app.getWechatPayNotifiyUrl(), app.getWechatPartnerKey());
		if (result == null) {
			DBMap map = order.getResponseData();
			renderResult(map, "微信下单失败", 500);
			return;
		}
		String code_url = result.get("code_url");
		String prepay_id = result.get("prepay_id");
		String trade_type = result.get("trade_type");
		order.setCodeUrl(code_url);
		order.setPrepayId(prepay_id);
		order.setTradeType(trade_type);
		order.update();

		/**
		 * 刷卡支付模式,需要返回值可以用这个方法
		 */
		if (mode == MODE_MICROPAY) {
		} else if (mode == MODE_QRCODE) {
			/**
			 * 二维码支付模式
			 */
			if (StrKit.isBlank(code_url)) {
				DBMap map = order.getResponseData();
				renderResult(map, "二维码错误", 500);
				return;
			}
			int img = getParaToInt("img", 0);
			// renderSuccess(code_url);
			DBMap map = order.getResponseData();
			map.put("qrcode", code_url);
			renderSuccess(map);
			if (img == 0) {
			} else if (img == 1) {
				// redirect("http://qr.liantu.com/api.php?text=" +
				// URLEncoder.encode(code_url));
				redirect("http://release.zhen-yee.com/api/qrcode?text=" + URLEncoder.encode(code_url));
			} else if (img == 2) {
				// String html = "<img
				// src='http://qr.liantu.com/api.php?text={}'/>";
				String html = "<img src='http://release.zhen-yee.com/api/qrcode?text={}'/>";
				html = StrFormatter.format(html, URLEncoder.encode(code_url));
				renderHtml(html);
			}
		} else {
		}
	}

	/**
	 * 刷卡支付
	 * 
	 * @param out_trade_no
	 * @param body
	 * @param total_fee
	 * @param detail
	 * @param goods_tag
	 * @param product_id
	 * @param attach
	 * @param authCode
	 * @return
	 */
	private boolean genMircoPay(String out_trade_no, String body, String total_fee, String detail, String goods_tag,
			String attach, String authCode, String appId, String partner, String partnerKey) {
		String url = "https://api.mch.weixin.qq.com/pay/micropay";

		// String total_fee = "1";
		// String auth_code = getPara("auth_code");// 测试时直接手动输入刷卡页面上的18位数字

		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", appId);
		params.put("mch_id", partner);
		// params.put("device_info", "javen205");// 终端设备号
		params.put("nonce_str", System.currentTimeMillis() / 1000 + "");
		params.put("body", body);
		if (StrKit.notBlank(detail)) {
			params.put("detail", detail);// 非必须
		}
		if (StrKit.notBlank(attach)) {
			params.put("attach", attach);// 附加参数非必须
		}
		if (StrKit.notBlank(goods_tag)) {
			params.put("goods_tag", goods_tag);
		}
		params.put("time_expire", DateUtil.format(new DateTime().plusMinutes(3).toDate(), "yyyyMMddHHmmss"));
		// String out_trade_no = System.currentTimeMillis() + "";
		params.put("out_trade_no", out_trade_no);
		params.put("total_fee", total_fee);

		String ip = IpKit.getRealIp(getRequest());
		if (StrKit.isBlank(ip)) {
			ip = "127.0.0.1";
		}

		params.put("spbill_create_ip", ip);
		params.put("auth_code", authCode);

		String sign = PaymentKit.createSign(params, partnerKey);
		params.put("sign", sign);

		String xmlResult = HttpUtils.post(url, PaymentKit.toXml(params));
		// 同步返回结果
		System.out.println("xmlResult:" + xmlResult);
		Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
		String return_code = result.get("return_code");
		if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
			// 通讯失败
			String err_code = result.get("err_code");
			// 用户支付中，需要输入密码
			if (err_code.equals("USERPAYING")) {
				// 等待5秒后调用【查询订单API】https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2
				return true;
			}
			renderText("通讯失败>>" + xmlResult);
			return false;
		}

		String result_code = result.get("result_code");
		if (StrKit.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
			// 支付失败
			renderText("支付失败>>" + xmlResult);
			return false;
		}

		// 支付成功 返回参会入库 业务逻辑处理

		renderText(xmlResult);
		// Map<String, String> resultMap = PaymentKit.xmlToMap(xmlResult);
		return true;
	}

	private Map<String, String> genPay(String out_trade_no, String body, String total_fee, String detail,
			String goods_tag, String product_id, String attach, String tradeType, String appId, String partner,
			String notifyUrl, String partnetKey) {

		String nonce_str = System.currentTimeMillis() / 1000 + "";
		// String nonce_str = RandomUtil.randomString(32);

		// if (DEBUG) {
		// total_fee = "1";
		// }

		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", appId);
		params.put("mch_id", partner);
		params.put("body", body);
		params.put("out_trade_no", out_trade_no);
		params.put("total_fee", total_fee);
		String ip = IpKit.getRealIp(getRequest());
		if (StrKit.isBlank(ip)) {
			ip = "127.0.0.1";
		}
		if (DEBUG) {
			ip = "127.0.0.1";
		}
		if (StrKit.notBlank(detail)) {
			params.put("detail", detail);
		}
		if (StrKit.notBlank(goods_tag)) {
			params.put("goods_tag", goods_tag);
		}
		params.put("spbill_create_ip", ip);
		if (StrKit.notBlank(tradeType)) {
			params.put("trade_type", tradeType);
		}
		params.put("product_id", product_id);
		params.put("nonce_str", nonce_str);
		params.put("notify_url", notifyUrl);
		params.put("time_expire", DateUtil.format(new DateTime().plusMinutes(5).toDate(), "yyyyMMddHHmmss"));
		// params.put("openid", openId);
		params.put("sign_type", "MD5");
		if (StrKit.notBlank(attach)) {
			params.put("attach", attach);
		}
		String sign = PaymentKit.createSign(params, partnetKey);
		params.put("sign", sign);
		String xmlResult = PaymentApi.pushOrder(params);
		Map<String, String> result = PaymentKit.xmlToMap(xmlResult);

		if (DEBUG) {
			LogKit.info(JsonKit.toJson(params));
			LogKit.info(xmlResult);
			LogKit.info("NOTIFY_URL: " + notifyUrl);
			LogKit.info("APP_ID: " + appId);
			LogKit.info("PARTNER: " + partner);
			LogKit.info("PARTNER_KEY: " + partnetKey + " - " + partnetKey.length());
		}
		if (!PayUtils.isXMLSuccess(result)) {
			LogKit.info(xmlResult);
			renderMsg("支付出错");
			return null;
		}
		return result;

		// String prepay_id = result.get("prepay_id");
		// DateTime dateTime = new DateTime();
		// String timeStamp = dateTime.toDate().getTime() / 1000 + "";
		// String signString = "appId=" + APP_ID + "&nonceStr=" + nonce_str +
		// "&package=prepay_id=" + prepay_id
		// + "&signType=MD5&timeStamp=" + timeStamp + "&key=" + PARTNER_KEY;
		// signString = HashKit.md5(signString).toUpperCase();
		// DBMap map = new DBMap();
		// map.put("result", result);
		// map.put("sign", signString);
		// map.put("timeStamp", timeStamp);
		// map.put("nonce_str", nonce_str);
		// // order.setPrepayId(prepay_id);
		// // order.update();
		// renderResult(map, "pay", 201);
		// return result.get("code_url");

	}

	@Before(YQSignInterceptor.class)
	public void microPay() {
		String ip = IpKit.getRealIpV2(getRequest());
		String key = "YQ_PAY_IP_" + ip;
		if (cache.get(key) != null) {
			renderFailure("too many connections");
			return;
		}
		cache.setex(key, 1, ip);
		String total = getPara("total");
		try {
			int price = Integer.parseInt(total);
			if (price <= 0) {
				renderFailure("total错误");
				return;
			}
		} catch (Exception e) {
			renderFailure("total错误");
			return;
		}
		String body = getPara("body", "商品");
		if (StrKit.notBlank(body)) {
			if (body.length() >= 200) {
				renderFailure("body长度错误");
				return;
			}
		}
		String detail = getPara("detail", "");
		if (StrKit.notBlank(detail)) {
			if (detail.length() >= 200) {
				renderFailure("detail长度错误");
				return;
			}
		}
		String goodsTag = getPara("goodsTag", "");
		if (StrKit.notBlank(goodsTag)) {
			if (goodsTag.length() >= 200) {
				renderFailure("goodsTag长度错误");
				return;
			}
		}
		String productId = getPara("productId", "商品标识");
		if (StrKit.notBlank(productId)) {
			if (productId.length() >= 200) {
				renderFailure("productId长度错误");
				return;
			}
		}
		String attach = getPara("attach", "");
		String notifyUrl = getPara("notifyUrl", "");
		String mark = getPara("mark", "");
		String data = getPara("data", "");

		// 单品优惠用到
		// https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_101&index=1
		// String version = getPara("version", "");

		if (StrKit.notBlank(data)) {
			if (data.length() >= 200) {
				renderFailure("data长度错误");
				return;
			}
		}
		String totalFee = total;
		Long suid = getParaToLong("suid");
		if (suid == null) {
			renderFailure();
			return;
		}
		YqShopUser shopUser = YqShopUser.dao.findById(suid);
		if (shopUser == null) {
			renderFailure(401, "无效账户，请重新登录");
			return;
		}
		// String shop = getPara("shop", "");
		// if (StrKit.isBlank(shop)) {
		// renderFailure("商户错误");
		// return;
		// }
		String shopCode = getPara("shop");
		Long shopId;
		try {
			shopId = YqOrder.LONG_HASHID.decode(shopCode)[0];
		} catch (Exception e) {
			System.out.println("shopCode: " + shopCode);
			renderFailure("商户错误");
			return;
		}
		YqShop shop = YqShop.dao.findById(shopId);
		if (shop == null) {
			renderFailure(404, "商户不存在");
			return;
		}
		YqApp app = shop.getApp();
		YqOrder order = new YqOrder(app);
		order.setIp(ip);
		order.setType(YqOrder.TYPE_THIRD);
		order.setNotifyUrl(notifyUrl);
		order.setTotalFee(totalFee);
		order.setMark(mark);
		order.setAttach(attach);
		// order.setMchId(PARTNER);
		// order.setAppId(APP_ID);
		order.setProductId(productId);
		order.setBody(body);
		order.setDetail(detail);
		order.setGoodsTag(goodsTag);
		order.setData(data);
		order.setShopId(shopId);
		order.save();
		String outTradeNo = YqOrder.genTradeNo() + YqOrder.MIN_HASHID.encode(order.getId());
		order.setOutTradeNo(outTradeNo);
		order.update();

		String authCode = getPara("authCode");
		if (StrKit.isBlank(authCode)) {
			renderFailure("authCode empty");
			return;
		}
		// boolean flag = genMircoPay(outTradeNo, body, totalFee, detail,
		// goodsTag,
		// attach, authCode);
		// if (!flag) {
		// renderFailure("mirco pay fail");
		// return;
		// }
		// DBMap responseMap = new DBMap();
		// responseMap.put("outTradeNo", outTradeNo);
		// renderSuccess(responseMap);

		String url = "https://api.mch.weixin.qq.com/pay/micropay";

		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", order.getAppId());
		params.put("mch_id", order.getMchId());
		// params.put("device_info", "javen205");// 终端设备号
		params.put("nonce_str", System.currentTimeMillis() / 1000 + "");
		params.put("body", body);
		if (StrKit.notBlank(detail)) {
			params.put("detail", detail);// 非必须
		}
		if (StrKit.notBlank(attach)) {
			params.put("attach", attach);// 附加参数非必须
		}
		if (StrKit.notBlank(goodsTag)) {
			params.put("goods_tag", goodsTag);
		}
		params.put("time_expire", DateUtil.format(new DateTime().plusMinutes(3).toDate(), "yyyyMMddHHmmss"));
		// String out_trade_no = System.currentTimeMillis() + "";
		params.put("out_trade_no", outTradeNo);
		params.put("total_fee", totalFee);

		String ip2 = IpKit.getRealIp(getRequest());
		if (StrKit.isBlank(ip2)) {
			ip2 = "127.0.0.1";
		}

		params.put("spbill_create_ip", ip2);
		params.put("auth_code", authCode);

		String sign = PaymentKit.createSign(params, app.getWechatPartnerKey());
		params.put("sign", sign);

		String xmlResult = HttpUtils.post(url, PaymentKit.toXml(params));
		// 同步返回结果
		System.out.println("xmlResult:" + xmlResult);
		Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
		String return_code = result.get("return_code");
		if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
			// 通讯失败
			renderFailure(result.get("return_msg"));
			return;
		}
		String result_code = result.get("result_code");
		String openId = result.get("openid");
		if (StrKit.notBlank(result_code) && "SUCCESS".equals(result_code)) {
			order.setOpenid(openId);
			order.update();
		}
		YqUser user = YqUser.dao.searchFirst("openId", openId);

		result.put("code", YqOrder.LONG_HASHID.encode(order.getId()));
		renderSuccess(result);

		// 新增扫码记录
		YqSaleRecord record = new YqSaleRecord();
		record.setOrderId(order.getId());
		record.setUserId(user.getId());
		record.setUserName(user.getNickName());
		record.setShopId(shopId);
		record.setShopName(shop.getName());
		record.setShopUserId(shopUser.getId());
		record.setShopUserName(shopUser.getName());
		record.setType(0); // 扫码支付
		record.setPrice(Float.valueOf(totalFee) / 100);
		record.save();

		// String result_code = result.get("result_code");
		// if (StrKit.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
		// // 支付失败
		// String err_code = result.get("err_code");
		// // 用户支付中，需要输入密码
		// if (err_code.equals("USERPAYING")) {
		// //
		// 等待5秒后调用【查询订单API】https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2
		// }
		// renderText("支付失败>>" + xmlResult);
		// }
		//
		// // 支付成功 返回参会入库 业务逻辑处理
		//
		// renderText(xmlResult);
	}

	@Before(SignInterceptor.class)
	public void directPay() {
		YqUser user = YqUser.dao.searchFirst("openId", getPara("openId"));
		Long userId = user.getId();

		String body = getPara("body", "");
		String detail = getPara("detail", "");
		String goodsTag = getPara("goodsTag", "");
		String notifyUrl = getPara("notifyUrl", "");
		String totalStr = getPara("total");
		if (!NumberUtil.isNumber(totalStr)) {
			renderFailure(500, "金额错误");
			return;
		}
		Integer total = null;
		try {
			total = Integer.parseInt(totalStr);
		} catch (Exception e) {
		}
		if (total == null) {
			renderFailure(500, "请提供金额");
			return;
		}
		if (total < 0) {
			renderFailure(500, "金额错误");
			return;
		}
		String shop = getPara("shop");
		Long shopId;
		try {
			shopId = HASHID.decode(shop)[0];
		} catch (Exception e) {
			e.printStackTrace();
			renderFailure(500, "商户号无效");
			return;
		}
		YqShop shopInfo = YqShop.dao.findById(shopId);
		if (shopInfo == null) {
			renderFailure(404, "无效商户");
			return;
		}

		String nationalCode = getPara("nationalCode", "");
		String telNumber = getPara("telNumber", "");
		String cityName = getPara("cityName", "");
		String postalCode = getPara("postalCode", "");
		String detailInfo = getPara("detailInfo", "");
		String provinceName = getPara("provinceName", "");
		String userName = getPara("userName", "");
		String countyName = getPara("countyName", "");
		int count = getParaToInt("count", 1);

		String remark = getPara("remark", "");

		YqApp app = shopInfo.getApp();

		YqOrder order = new YqOrder(app);
		order.setOutTradeNo(YqOrder.genTradeNo());
		order.setTotalFee(String.valueOf(total));
		// order.setAppId(APP_ID);
		order.setBody(body);
		order.setDetail(detail);
		order.setGoodsTag(goodsTag);
		order.setNotifyUrl(notifyUrl);
		order.setShopId(shopId);
		String openid = user.getOpenId();
		order.setOpenid(openid);
		boolean pushFlag = order.pushOrder(IpKit.getRealIpV2(getRequest()));
		if (!pushFlag) {
			renderFailure("下单失败");
			return;
		}

		order.setUserId(userId);
		order.save();

		YqOrderInfo newOrderInfo = new YqOrderInfo();
		// newOrderInfo.setType(YqOrder.TYPE_PRODUCT);
		newOrderInfo.setName(userName);
		newOrderInfo.setMobile(telNumber);
		newOrderInfo.setAddress(provinceName + cityName + countyName + detailInfo);
		newOrderInfo.setCount(count);
		newOrderInfo.setPostalCode(postalCode);
		newOrderInfo.setNationalCode(nationalCode);
		newOrderInfo.setRemark(remark);

		Long orderId = order.getId();
		newOrderInfo.setIsNeedTrack(0);
		// newOrderInfo.setProductId(productId);
		newOrderInfo.setOrderId(orderId);
		// newOrderInfo.setTitle(product.getTitle());
		newOrderInfo.setTitle(body);
		// newOrderInfo.setCover(product.getCover());
		newOrderInfo.setIntro(detail);
		newOrderInfo.setPrice(String.valueOf(total));
		newOrderInfo.setUserId(userId);
		// newOrderInfo.setRefId(productId);
		String code = HASHID.encode(orderId);
		newOrderInfo.setHashId(code);
		// newOrderInfo.setItemId(itemId);
		// String qrcodeImageUrl = "http://qr.liantu.com/api.php?text=" + code;
		String qrcodeImageUrl = "http://release.zhen-yee.com/api/qrcode?text=" + code;
		newOrderInfo.setQrcode(qrcodeImageUrl);
		newOrderInfo.save();

		order.update();
		renderPay(order);
	}

	protected void renderPay(YqOrder order) {
		YqApp app = order.getApp();
		renderPay(order.getPrepayId(), app.getWechatMiniAppId(), app.getWechatPartnerKey());
	}

	protected void renderPay(String prepay_id, String appId, String partnerKey) {
		// String nonce_str = System.currentTimeMillis() / 1000 + "";
		String nonce_str = RandomUtil.randomString(32);

		DateTime dateTime = new DateTime();
		String timeStamp = dateTime.toDate().getTime() / 1000 + "";
		String signString = "appId=" + appId + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id
				+ "&signType=MD5&timeStamp=" + timeStamp + "&key=" + partnerKey;
		signString = HashKit.md5(signString).toUpperCase();
		DBMap map = new DBMap();
		map.put("sign", signString);
		map.put("timeStamp", timeStamp);
		map.put("nonce_str", nonce_str);
		map.put("package", prepay_id);
		map.put("prepay_id", prepay_id);
		map.put("signType", "MD5");
		renderResult(map, "pay", 200);
	}

	/**
	 * 未用微信扫码h5页面
	 */
	public void payInfo() {
		render("/yq/qrcodeInfo.html");
	}

	/**
	 * 未用微信扫码h5页面
	 */
	public void productInfo() {
		render("/yq/qrcodeInfo.html");
	}

	/**
	 * 更新随机有趣的索引
	 */
	@Before({ TestInterceptor.class })
	public void updateItemIndex() {
		yqUtils.updateItemIndex();
		renderSuccess();
	}

	/**
	 * 更新已购用户头像
	 */
	@Before({ TestInterceptor.class })
	public void updateProductPaidUsers() {
		Long productId = getParaToLong("productId");
		if (productId == null) {
			renderFailure();
			return;
		}
		YqProduct product = YqProduct.dao.findById(productId);
		product.updatePaidUsers();
		renderSuccess(product);
	}

	/**
	 * 获取商户信息
	 */
	public void shopInfo() {
		String code = getPara("code");
		Long shopId;
		try {
			shopId = HASHID.decode(code)[0];
		} catch (Exception e) {
			e.printStackTrace();
			renderFailure(500, "商户号无效");
			return;
		}
		YqShop shopInfo = YqShop.dao.findById(shopId);
		if (shopInfo == null) {
			renderFailure(404, "无效商户");
			return;
		}
		renderResult(shopInfo);
	}

	/**
	 * 发送验证短信
	 */
	public void sms() {
		String project = getPara("project");
		// if (StrKit.isBlank(project)) {
		// renderFailure();
		// return;
		// }
		String mobile = getPara("mobile", "13631290232");
		ZHSMSUtils yqsmsUtils = new ZHSMSUtils();
		Ret ret = yqsmsUtils.sendSMS(mobile, true);
		System.out.println(ret.get("msg"));
		renderSuccess(ret.get("msg"));
	}
}
